package org.zebra.monitoring.processor;

import cn.hutool.core.net.NetUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.logging.DeferredLogFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;

import java.util.Properties;

public class MonitorEnvironmentPostProcessor implements EnvironmentPostProcessor {

    private Log log;

    /**
     * 使用 DeferredLog 输出日志，因为日志组件还没有初始化
     *
     * @param deferredLogFactory 对象
     */
    public MonitorEnvironmentPostProcessor(DeferredLogFactory deferredLogFactory) {
        log = deferredLogFactory.getLog(MonitorEnvironmentPostProcessor.class);
    }

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        String contextPath = environment.getProperty("serverservlet..context-path", "");
        String port = StringUtils.isNotBlank(environment.getProperty("server.port"))
                ? environment.getProperty("server.port")
                : "8080";
        String enabled = environment.getProperty("zebra.monitor.ko-time.enabled");
        if (StringUtils.isBlank(enabled)) {
            enabled = "false";
        }
        Properties properties = new Properties();
        properties.setProperty("koTime.enable", enabled);
        String pointcut = environment.getProperty("zebra.monitor.ko-time.pointcut");
        if (StringUtils.isNotBlank(pointcut) && enabled.equals("true")) {
            String logEnable = environment.getProperty("zebra.monitor.ko-time.logEnable");
            String language = environment.getProperty("zebra.monitor.ko-time.language");
            String threshold = environment.getProperty("zebra.monitor.ko-time.threshold");
            String exceptionEnable = environment.getProperty("zebra.monitor.ko-time.exceptionEnable");
            String authEnable = environment.getProperty("zebra.monitor.ko-time.authEnable");
            String userName = environment.getProperty("zebra.monitor.ko-time.userName");
            String password = environment.getProperty("zebra.monitor.ko-time.password");
            String paramAnalyse = environment.getProperty("zebra.monitor.ko-time.paramAnalyse");
            String dataReset = environment.getProperty("zebra.monitor.ko-time.dataReset");
            String threadNum = environment.getProperty("zebra.monitor.ko-time.threadNum");
            String discardRate = environment.getProperty("zebra.monitor.ko-time.discardRate");
            String authExpire = environment.getProperty("zebra.monitor.ko-time.authExpire");
            String versionNotice = environment.getProperty("zebra.monitor.ko-time.versionNotice");
            // 动态添加属性值
            properties.setProperty("koTime.pointcut", pointcut);
            properties.setProperty("koTime.logEnable", StringUtils.isNotBlank(logEnable) ? logEnable : "false");
            properties.setProperty("koTime.language", StringUtils.isNotBlank(language) ? language : "chinese");
            properties.setProperty("koTime.threshold", StringUtils.isNotBlank(threshold) ? threshold : "800");
            properties.setProperty(
                    "koTime.exceptionEnable", StringUtils.isNotBlank(exceptionEnable) ? exceptionEnable : "false");
            properties.setProperty("koTime.authEnable", StringUtils.isNotBlank(authEnable) ? authEnable : "false");
            if (StringUtils.isNotBlank(authEnable)) {
                properties.setProperty("koTime.userName", userName);
                properties.setProperty("koTime.password", password);
            }
            properties.setProperty("koTime.paramAnalyse", StringUtils.isNotBlank(paramAnalyse) ? paramAnalyse : "true");
            properties.setProperty("koTime.dataReset", StringUtils.isNotBlank(dataReset) ? dataReset : "false");
            properties.setProperty("koTime.threadNum", StringUtils.isNotBlank(threadNum) ? threadNum : "2");
            properties.setProperty("koTime.discardRate", StringUtils.isNotBlank(discardRate) ? discardRate : "0.3");
            properties.setProperty("koTime.authExpire", StringUtils.isNotBlank(authExpire) ? authExpire : "43200");
            properties.setProperty(
                    "koTime.versionNotice", StringUtils.isNotBlank(versionNotice) ? versionNotice : "true");
        }
        String adminEnabled = environment.getProperty("zebra.monitor.admin.enabled", "false");
        if (Boolean.parseBoolean(adminEnabled)) {
            properties.setProperty("spring.boot.admin.client.url", "http://localhost:" + port);
            properties.setProperty("management.endpoints.web.exposure.include", "*");
            log.info("springboot admin web console http://" + NetUtil.getLocalhostStr() + ":" + port + contextPath
                    + "/applications");
        }
        String arthasEnabled = environment.getProperty("zebra.monitor.arthas.enabled");
        if (StringUtils.isNotBlank(arthasEnabled) && arthasEnabled.equals("true")) {
            String telnetPort = environment.getProperty("zebra.monitor.arthas.telnet-port");
            String httpPort = environment.getProperty("zebra.monitor.arthas.http-port");
            String ip = environment.getProperty("zebra.monitor.arthas.ip");
            properties.setProperty("arthas.telnetPort", StringUtils.isNotBlank(telnetPort) ? telnetPort : "3658");
            properties.setProperty("arthas.httpPort", StringUtils.isNotBlank(httpPort) ? httpPort : "8563");
            properties.setProperty("arthas.ip", StringUtils.isNotBlank(ip) ? ip : "127.0.0.1");
            log.info("arthas web console http://" + NetUtil.getLocalhostStr() + ":"
                    + properties.getProperty("arthas.httpPort") + contextPath);
        } else {
            properties.setProperty("spring.arthas.enabled", "false");
        }
        String javamelodyEnabled = environment.getProperty("zebra.monitor.javamelody.enabled");
        if (StringUtils.isNotBlank(javamelodyEnabled) && javamelodyEnabled.equals("true")) {
            log.info("javamelody web console http://" + NetUtil.getLocalhostStr() + ":" + port + contextPath
                    + "/monitoring");
        } else {
            properties.setProperty("javamelody.enabled", "false");
        }
        String swaggerEnabled = StringUtils.isNotBlank(environment.getProperty("zebra.web.swagger.enabled"))
                ? environment.getProperty("zebra.web.swagger.enabled")
                : "true";
        if (swaggerEnabled.equals("true")) {
            properties.setProperty("spring.mvc.pathmatch.matching-strategy", "ant_path_matcher");
        }
        environment.getPropertySources().addLast(new PropertiesPropertySource("monitorProperties", properties));
    }
}
